#ifndef _RESOURCE_MANAGE_H
#define _RESOURCE_MANAGE_H

#include "gp_layout_map.h"

#ifdef x86_64
#define REAGENT_FILE "/home/hcgy/Documents/esm6800h/test/schedule/reagent.json"
#else
#define REAGENT_FILE "/mnt/nandflash/apps/config/reagent.json"
#endif

#ifdef x86_64
#define TIPS_FILE "/home/hcgy/Documents/esm6800h/test/schedule/tips.json"
#else
#define TIPS_FILE "/mnt/nandflash/apps/config/tips.json"
#endif

typedef enum
{
   QPCR_REAGENT_AREA_REAGENT,
   QPCR_REAGENT_AREA_48HOLES,

   PURIFY_AREA_SAMPLE,
   PURIFY_AREA_DJ_REAGENT,
   PURIFY_AREA_TIPS_DP1,
   PURIFY_AREA_TIPS_DP8,
   PURIFY_AREA_FILM,
   PURIFY_AREA_DP8_REAGENT,
   PURIFY_AREA_SHAKE,
}en_topology_loc_type;

typedef struct _sample_describe
{
    location_layout sampleLoc;
    int sample_type;//blood, splittle
}sample_describe;

typedef enum 
{
    REAGENT_BREAK,//splitting the cell
    DJP_REAGENT_START = REAGENT_BREAK,
    REAGENT_PROTAINASE,
    REAGENT_MAGNET,    
    REAGENT_HELPDOWN,
    DJP_REAGENT_END = REAGENT_HELPDOWN,
    
    REAGENT_INTERNAL_REFERENCE,
    DP1_REAGENT_START = REAGENT_INTERNAL_REFERENCE,
    DP1_REAGENT_END = REAGENT_INTERNAL_REFERENCE,
    
    REAGENT_WASHOFF,   
    DP8_REAGENT_START = REAGENT_WASHOFF,
    REAGENT_CLEAN1,
    REAGENT_CLEAN2,
    REAGENT_CLEAN3,
    DP8_REAGENT_END = REAGENT_CLEAN3,

    REAGENT_QPCR,
    DJQ_REAGENT_START = REAGENT_QPCR,
    DJQ_REAGENT_END = REAGENT_QPCR,
}en_reagent_type;

typedef struct _reagent_describe
{
    int container_type;
    unsigned short indexX;
    unsigned short indexY;
    unsigned short index_module_X;
    unsigned short index_module_Y;

    int reagent_type;
    int is8Conbined;
    int needPurify;
    int volumeRemain;
}reagent_describe;

typedef struct _source_loc
{
    unsigned short indexX;
    unsigned short indexY;
    unsigned short index_module_X;
    unsigned short index_module_Y;
}source_loc;

typedef enum
{
    TIP_1000UL,
    TIP_200UL,
    TIP_50UL,
}en_tip_type;

typedef enum
{
    PUMP_5000UL,
    PUMP_250UL,
    PUMP_2500UL,
}en_pump_type;


typedef struct _tip_describe
{
    unsigned char index_x;
    unsigned char index_y;
    unsigned char isAvailable;
    unsigned char reserved;
    struct _tip_describe * next;
}tip_describe;

int load_one_group_reagent(const void * jsonNodeIn,reagent_describe ** reagentArrOut,int * numOut,int moduleIdIn);

typedef enum
{
    DP8_LIQUID_TYPE,
    DP1_LIQUID_TYPE,
    DJ_PURIFY_LIQUID_TYPE,
    DJ_QPCR_LIQUID_TYPE,
    MAX_NUM_MODULE_LIQUID_TYPE,
}en_liquid_type_module;

class CReagent
{
private:
    reagent_describe * m_reagent_qpcr_arr;
    int m_num_qpcr_reagent;
    reagent_describe* m_reagent_dj_purify_arr;
    int m_num_djp_reagent;
    reagent_describe * m_reagent_dp8_arr;
    int m_num_dp8_reagent;

    unsigned char m_liquidTypeArr[MAX_NUM_MODULE_LIQUID_TYPE];
public:
    int init_reagent_from_config(const char * file_name);
    int apply_reagent_to_suck(int typeIn, float volumeIn, reagent_describe ** pstReagentOut,float *volumnOut);
    int update_reagent(reagent_describe * reagentIn);

    void setModuleLiquidType(int moduleIn,unsigned char liquidTypeIn);
    unsigned char getLiquidType(int moduleIn);

    int getRemainVolume(int moudleId, location_layout* plocIn);

    void setRemainVolume(int moudleId, location_layout* plocIn, int volumeToSet);
        
    CReagent();
    virtual ~CReagent();
};

typedef enum
{
    ALL_AVAILEBLE,
    PART_AVAILABLE,
    NO_AVLAIBLE,
}en_tip_box_status;

typedef struct _tip_box
{
    unsigned char module_i_x;
    unsigned char module_i_y;
    unsigned char max_row_y;
    unsigned char max_colum_x;
    
    unsigned char tipType;
    unsigned char status;
    unsigned char remainNum;
    unsigned char reserved2;
    
    tip_describe * tipMem;

    tip_describe * tipList;    

}tip_box;

class CTips
{
private:
    tip_box * m_tip_box_dp8_arr;
    int m_numDp8TipBox;
    tip_box * m_tip_box_dp1_arr;
    int m_numDp1TipBox;

    int m_currentDp1TipType;
    int m_currentDp8TipType;
    int m_currentDp8_1TipType;
public:
    int init_tips_from_config(const char * file_name);
    int apply_tip_to_use(int userType, int tipType,tip_box **pstTipBoxOut, tip_describe ** tipOut);
    int update_tip(tip_box *pstTipBoxOut);

    void setCurrTipType(int moduleIn,int tipType);
    int getCurrTipType(int moduleIn);    
    CTips();
    virtual ~CTips();
};

#define MAX_NUM_HOLES_ONE_TUBE8 8

typedef struct _tube8_describe
{
    loc_base tube8InitLoc;
    loc_base tube8CurrLoc;
    int currHoleIndexDp1;
    int currStage;
    int volumeRemain[MAX_NUM_HOLES_ONE_TUBE8];
}tube8_describe;

#define MAX_NUM_TUBE8_ONE_AREA 6

#define MAX_LEN_PARAM 1024

class CTube_8Holes
{
private:
    tube8_describe * m_tube8_arr_a;
    tube8_describe * m_tube8_arr_b;
    int m_currDp8Index;
    int m_currDP1Index;

    char * paramMem_a[MAX_NUM_TUBE8_ONE_AREA];

    char * paramMem_b[MAX_NUM_TUBE8_ONE_AREA];
public:
    int init_tube8(int tube8Id,int areaId);
    int get_hole(int userType, tube8_describe * holeOut);

    int change_stage(int tube8Id,int areaId,int targetStage);

    int update_tube8(tube8_describe * tube8In, const int numIn);
        
    CTube_8Holes();
    virtual ~CTube_8Holes();

    int getRemainVolume(location_layout * locIn, int tube8IdIn);
    void setRemainVolume(location_layout * locIn,int tube8IdIn, int volume);
};


typedef struct _suck_ctl
{
    float air1;
    float air2;
    float speedSuck;
    float liquidMore;
    float spitQuan;
    unsigned int spitSpeed;//inc/s
}suck_ctl;


extern const suck_ctl djSuckCtlParam[];

typedef enum
{
   PURIFY_PUMP_SMALL,
   PURIFY_PUMP_BIG
}en_purify_pump_type;

class CResource_Manage
{
private:
    CTube_8Holes * m_pstTube8;
    CTips * m_pstTips;
    CReagent * m_pstReagent;
    int m_curr_purify_pump;
public:
    void set_curr_tip_type(int moduleIn,int tipTypeIn);
    int get_curr_tip_type(int moduleIn);
    CResource_Manage();
    virtual ~CResource_Manage();

    void set_curr_liquid_type(int moduleIn,int tipTypeIn);
    unsigned char get_curr_liquid_type(int moduleIn);

    void set_purify_pump_type(int purifyPumpTpeIn);
    int get_purify_pump_type(void);

};

CResource_Manage * getResourceManage(void);

#endif
